import g4p_controls.*;
import processing.video.*;
import blobscanner.*;


Capture cam;
Boolean takeSnapshot=false;
PImage snapshot;
TileContainer tileContainer;
boolean rankingWindowOpen = false;
Boolean gameStarted = false;
Boolean rankingShown = false;
Boolean restart = false;
int savedTime;
int scoreTime;
XML xml;
Boolean isSaved = false;

//gesty
PImageOperations  PImOps;
PBGS  pBackground;
FingerDetector fd  ;
Detector bs, bstips;

final int TIPS_MASS = 45;
final int HAND_MASS = 600;

int iThreshold = 190;
boolean iSetNext = true;

PFont f;
PImage tips = createImage(320,240, RGB); 
PImage imgDiff = createImage(320,240, RGB); 
PImage  FG = createImage(320,240,RGB); 
PImage  imgDiffColor = createImage(320,240,RGB);


void setup() {
  movement=new StringList();
  xml = loadXML("ranking.xml");

  String[] cameras = Capture.list();
  snapshot=loadImage("data/as.png");
  createGUI();
  if (cameras.length == 0) {
    exit();
  } 
  // The camera can be initialized directly using an 
  // element from the array returned by list():
  //cam = new Capture(this, cameras[0]);
  cam = new Capture(this, 320, 240 );
  cam.start();


  size(640, 640, JAVA2D);
  
  
  //size(700,540);
  //f = createFont("", 20);
  //textFont(f, 20);
 

  PImOps = new PImageOperations();
  pBackground = new PBGS(FG);
  fd = new FingerDetector(640, 640 );
  bs = new Detector(this, 0, 0, 640, 640, 255);
  bstips = new Detector(this, 0, 0, 640, 640, 255);
  
  
}


void draw() {
  //rysuj GUI
  if (gameStarted && !rankingShown) {
    customGUI(4, "null");
  } else
  {
    customGUI(3, "null");
  }
  //Pokazuj obraz z kamery, jeżeli nie zostało zrobione zdjęcie
  if (cam.available() == true && takeSnapshot==false ) 
  {
    cam.read();
    image(cam, OFFSET, 0, CAMERA_SCREEN_SIZE, CAMERA_SCREEN_SIZE);
  }
  //jeżeli wciśnięty został klawisz i nie zostało wcześniej zrobione zdjęcie , to zrób zdjęcie
  if (takeSnapshot==false && gameStarted)
  {
    takeSnapshot=true;
    saveFrame("data/snapshot.jpg"); 
    snapshot=loadImage("data/snapshot.jpg");
    //pocięcie screenShota na ten który mamy przerabiać
    tileContainer=new TileContainer(DIMENSION, snapshot.get(OFFSET, 0, CAMERA_SCREEN_SIZE, CAMERA_SCREEN_SIZE));
    background(123);
    customGUI(1, "Shuffle in order:");
    for (int i=0; i<movement.size (); i++)
    {
      customGUI(1, movement.get(i));
    }
  }
  // Jeżeli został już zrobione zdjęcie.
  if (takeSnapshot==true)
  {   
    background(123);
    tileContainer.display();
    
              // gesty
      cam.read();
      cam.loadPixels();
      FG.loadPixels();
      
      arrayCopy(cam.pixels,FG.pixels);       //put this into a PImage
     
      FG.updatePixels();
     
      if (iSetNext)
      {
        pBackground.Set(FG);                    // Set the background image
        iSetNext=false;
      }                 
      pBackground.Update(FG);                   // Update the background model
      pBackground.PutDifference();              // Put the difference in imgDiff
      
      
      //  FINGER DETECTION   //
     
      imgDiff.loadPixels();
      //fd.setImage(imgDiff);                     // ustaw pixele z reki w BGS
      imgDiff.updatePixels();
      
      bs.imageFindBlobs(imgDiff);               // ogarniaj blobsy w BGS
      bs.loadBlobsFeatures();
      bs.weightBlobs(false);
     
       drawFingersTips();                       
       //drawFingersTipsBoundingBox();
       drawDiffColorImageBoundingBox();    
    
  }
  
 
  
  // WYGRANA
  if (WINNER)
  {
    println("WYGRAŁEŚ/WYGRAŁAŚ");

    if (!rankingShown) {
      // customGUI(3,"null");
      XML[] children = xml.getChildren("player");

      rankingWindow = new GWindow(this, "Ranking", 0, 0, 240, 480, false, JAVA2D);
      rankingWindow.setActionOnClose(G4P.CLOSE_WINDOW);
      rankingWindow.addDrawHandler(this, "win_draw1");
      label3 = new GLabel(rankingWindow.papplet, 10, 9, 220, 390);
      for (int i = 0; i < children.length; i++)
      {
        label3.setText(label3.getText()+"\n"+children[i].getString("id")+":  "+ children[i].getString("name")+"   "+ children[i].getString("score") );
      }

      label3.setOpaque(true);


      scoreTime = (savedTime-millis())/100;
      button3 = new GButton(rankingWindow.papplet, 130, 430, 80, 30);
      button3.setText("save");
      button3.addEventHandler(this, "button3_click1");

      textfield1 = new GTextField(rankingWindow.papplet, 7, 430, 110, 30, G4P.SCROLLBARS_NONE);
      textfield1.setText("name");
      textfield1.setOpaque(true);
      textfield1.addEventHandler(this, "textfield1_change1");
    }
    rankingShown = true;
  }
}
public void customGUI(int mode, String massage) {
  switch(mode)
  {
  case 1:
    label1.setText(label1.getText()+"\n"+massage);
    break;
  case 2:
    label1.setText(massage+"\n");
    break;
  case 3:
    label2.setText("Your time:" + scoreTime*(-1));
    break;
  case 4:
    label2.setText("Your time:" + (millis()-savedTime)/100+"");
    break;
  }
}

public void setDifficulty() {


  switch(DIFFICULT)
  {
  case EASY:
    DIMENSION=3;

    break;
  case MEDIUM:
    DIMENSION=4;
    break;
  }
  TILESIZE=CAMERA_SCREEN_SIZE/DIMENSION;
}


/*
  analiza blobsow i zliczanie plauchow
 */
 
void drawText(){
   int fingersCount = 0;
   fill(255);
 
   for(int i = 0; i < bstips.getBlobsNumber(); i++){
     if(bstips.getBlobWeight(i) >= TIPS_MASS) 
     fingersCount++;
    }
     text(fingersCount + " finger tips detected" ,  30 ,height-50);                                  
 }
 
 
 /*
   wykrywanie reki -> analiza pixeli w blobsach 
 */
 void drawFingersTips(){
   
  tips.loadPixels();
  
  for(int i = 0; i < 320*240; i++)tips.pixels[i] = 0xff000000 ;// czarrnyyy
  
  //dla kazdego pixela BGS (imgDiff)....
  for(int y =  0; y < 240; y++){
    for(int x =  0; x < 320; x++){
     if(bs.isBlob(x, y) && bs.getBlobWeightLabel(bs.getLabel(x, y))>= HAND_MASS){      // jesli wykryto reke  
 
     if(fd.goodPixel(x, y))                              //jesli wylryto pixel palucha zmien na bialy
     tips.pixels[x+y*tips.width] = 0xff << 16 & 0xff0000 | 0xff << 8 & 0xff00 | 0xff & 0xff;
     
         } 
      }
   }
   
   tips.updatePixels();
   
   bstips.imageFindBlobs(tips);
   bstips.loadBlobsFeatures();
   bstips.weightBlobs(false); 
   drawText();
 
   //image(tips,360,20);                         // wyswietlanie wykrytych paluchow
 }

 void drawFingersTipsBoundingBox(){
   pushMatrix();
   translate(640,640);
   bstips.drawBox(color(255,0,0),1);
   popMatrix();
 }
 
 void drawDiffColorImageBoundingBox(){
   pushMatrix();
   translate(20,20);
   bs.drawSelectBox(600,255,1);
   popMatrix(); 
   
 }

